#pragma once

// 我们将在这里定义三种Thread: CThreadEx, CThreadBase, CTasksThread
// 第一种CThreadEx需要传入线程函数的指针，CThreadBase作为基类使用，CTasksThread
// 则构建一个内部包含任务列表的、可向它派发异步任务的线程。

#include <pthread.h>
#include <signal.h>
#include <errno.h>
#include "util/NonCopyable.h"

typedef void *(*LPTHREAD_START_ROUTINE)(void *);

namespace qcutil {
/**
 * @brief The CThreadBase class
 * 这个线程类需要传入线程函数。
 * 这个函数从NonCopyable中继承，我不希望线程对象到处复制以免线程被多次杀死或者多次启动。
 */
class CThreadBase : public NonCopyable
{
public:
    CThreadBase(void);
    virtual ~CThreadBase(void);
public:
    /**
     * @brief create 创建线程
     * @param lpStartAddress 线程函数指针
     * @param lpParameter 传递给线程的参数。
     * @return 如创建成功返回true，否则返回false。
     */
    bool create(LPTHREAD_START_ROUTINE lpStartAddress, void* lpParameter = NULL);

    /**
     * @brief terminate 强制杀死线程。
     * @return
     */
    bool terminate();

    /**
     * @brief alive 询问线程时候存活。
     * @return
     */
    bool alive();

    /**
     * @brief join 等待线程结束运行，如果线程内无退出点（无限循环）请不要调用这个方法。
     */
    void join();

    /**
     * @brief waitToEndKill 等待一段时间，如果线程还不退出就强制杀死它。
     * @param waitTime 等待时间，单位为毫秒。
     */
    void waitToEndKill(unsigned int waitTime = 1000);

    /**
     * @brief close 清理线程资源占用，注意这个函数不能结束线程的执行，应当调用join、waitToEndKill或terminate函数。
     * @return
     */
    void close();

    bool isCurrentThread(){
        return 0 != pthread_equal(m_thread, pthread_self());
    }

private:
    pthread_t m_thread;
};

/**
 * @brief The CThread class
 * 这个线程类内置了一个工作线程，如果希望对象内置线程则可从这个对象派生。
 * 如使用此对象则必须实现它的onThread接口，在这里做线程中需要做的事情。
 * 注意由于CThreadBase继承自NonCopyable，所以它也是不可拷贝的。
 */
class CThread : public CThreadBase
{
public:
    CThread(){}
    virtual ~CThread(){}
public:
    virtual void onThread() = 0;
    // overwrite
    bool create()
    {
        return CThreadBase::create(myThread, this);
    }
private:
    static void* myThread(void* thread_param)
    {
        CThread* p = (CThread*)(thread_param);
        p->onThread();
        return NULL;
    }
};
}
